#include "cholidayset.h"

#include "cworktime.h"

CHolidaySet::CHolidaySet() {}

int CHolidaySet::DiffSeconds(const QDateTime & rStartDateTime, const QDateTime & rEndDateTime)
{
    //qDebug() << CCommon::ToString(rStartDateTime) << " " << CCommon::ToString(rEndDateTime);
    if (rStartDateTime >= rEndDateTime) {//已经逾期
        return 0;
    }
    QTime startTime = rStartDateTime.time();
    QTime endTime = rEndDateTime.time();
    QDate startDate = rStartDateTime.date();
    QDate endDate = rEndDateTime.date();
    int iDiffDays = rStartDateTime.daysTo(rEndDateTime);
    QMap<QDate, QVector<CWorkTime> > hashDateToWorkTime;
    CapDateWorkTime(startDate, endDate, hashDateToWorkTime);
    if (iDiffDays == 0)
    {//今天与交期同一天
        return SameDayLeftSeconds(endDate, startTime, endTime, hashDateToWorkTime);
    }
    else
    {
        int iLeftWorkTime = 0;
        iLeftWorkTime += TodayLeftSeconds(startDate, startTime, hashDateToWorkTime);
        iLeftWorkTime += FinalLeftSeconds(endDate, endTime, hashDateToWorkTime);
        for (unsigned int i = 1; i < iDiffDays; ++i)
        {
            QDate curDate = startDate.addDays(i);
            if (hashDateToWorkTime.find(curDate) == hashDateToWorkTime.end()) continue;
            const QVector<CWorkTime>& rVecWorkTime = hashDateToWorkTime[curDate];
            if (rVecWorkTime.isEmpty())
            {
                iLeftWorkTime += 0;
            }
            else
            {
                iLeftWorkTime += TodayLeftSeconds(curDate, rVecWorkTime.constFirst().mWorkStartTime, hashDateToWorkTime);
            }
        }
        return iLeftWorkTime;
    }
}

int CHolidaySet::SameDayLeftSeconds(const QDate rDate, const QTime & rCurTime,
                                    const QTime& rFinalTime, const QMap<QDate, QVector<CWorkTime> >& rDateToWorkTime)
{
    if (rDateToWorkTime.find(rDate) == rDateToWorkTime.end()) return 0;
    return OneDayLeftSeconds(rDateToWorkTime[rDate], rCurTime, rFinalTime);
}

bool CHolidaySet::CapDateWorkTime(const QDate & rStartDate, const QDate & rEndDate, QMap<QDate, QVector<CWorkTime> >& rHashDayToWorkTime)
{
    if (rEndDate < rStartDate) return false;
// 	CDBObj dbObj(CDBOpt::openConnection()); QSqlDatabase& db = dbObj.DB();
// 	try {
// 		QSqlQuery query(db);
// 		QString strSql = QString("select appointed_date, work_time_start, work_time_end from %1 with (NOLOCK) \
// where appointed_date >= '%2' and appointed_date <= '%3' order by appointed_date, work_time_start")
// .arg(T_DATE_WORK_TIME_SET).arg(CCommon::ToString(rStartDate)).arg(CCommon::ToString(rEndDate));
// #ifdef _DEBUG
// 		QString s;
// 		s = QString("请求50：%1").arg(strSql);
// 		theApp.sqlLog->Log(s);
// #endif
// 		query.setForwardOnly(true);
// 		query.prepare(strSql);
// 		CDBOpt::Exec(query);
// 		while (query.next()) {
// 			int iFieldIndex = 0;
// 			QDate appointedDate = query.value(iFieldIndex++).toDate();
// 			CWorkTime obj;
// 			QTime StartTime = query.value(iFieldIndex++).toTime();
// 			QTime EndTime = query.value(iFieldIndex++).toTime();
// 			obj.update(StartTime, EndTime);
// 			rHashDayToWorkTime[appointedDate].push_back(obj);
// 		}
// 		query.clear();

// 	}
// 	catch (int iErrCode) {
// 		//mErrInfo = "查询上下班时间失败：" + CDBOpt::mErrInfo;

// 		return false;
// 	}
    CapHoliday(rStartDate, rEndDate);
    int iTotalDays = rStartDate.daysTo(rEndDate) + 1;
    for (unsigned int i = 0; i < iTotalDays; ++i) {
        QDate curDate = rStartDate.addDays(i);

        if (rHashDayToWorkTime.find(curDate) == rHashDayToWorkTime.end()) {//在指定日期中找不到
            if (mSetHoliday.constFind(curDate) == mSetHoliday.constEnd()) {//在放假日期中找不到
                int iDayIndex = curDate.dayOfWeek() - 1;
                if (mHashNormalDayToWorkTime.constFind(iDayIndex) != mHashNormalDayToWorkTime.constEnd()) {
                    rHashDayToWorkTime[curDate] = mHashNormalDayToWorkTime[iDayIndex];
                }
            }
        }
    }
    return true;
}

void CHolidaySet::CapHoliday(const QDate & rStartDate, const QDate & rEndDate)
{
//	mSetHoliday.clear();
// 	if (rEndDate < rStartDate) return;
// 	CDBObj dbObj(CDBOpt::openConnection()); QSqlDatabase& db = dbObj.DB();
// 	try {
// 		QSqlQuery query(db);
// 		QString strSql = QString("select holiday_date from %1 with (NOLOCK) \
// where holiday_date >= '%2' and holiday_date <= '%3' order by holiday_date")
// .arg(T_HOLIDAY).arg(CCommon::ToString(rStartDate)).arg(CCommon::ToString(rEndDate));
// #ifdef _DEBUG
// 		QString s;
// 		s = QString("请求48：%1").arg(strSql);
// 		theApp.sqlLog->Log(s);
// #endif
// 		query.setForwardOnly(true);
// 		query.prepare(strSql);
// 		CDBOpt::Exec(query);
// 		while (query.next()) {
// 			int iFieldIndex = 0;
// 			QDate appointedDate = query.value(iFieldIndex++).toDate();
// 			mSetHoliday.insert(appointedDate);
// 		}
// 		query.clear();

// 	}
    // catch (int iErrCode) {

    // }
}

int CHolidaySet::TodayLeftSeconds(const QDate rDate, const QTime & rCurTime,
                                  const QMap<QDate, QVector<CWorkTime> >& rDateToWorkTime)
{
    if (rDateToWorkTime.find(rDate) == rDateToWorkTime.end()) return 0;
    const QVector<CWorkTime> & rVecWorkTime = rDateToWorkTime[rDate];
    return OneDayLeftSeconds(rVecWorkTime, rCurTime, rVecWorkTime.constLast().mWorkEndTime);
}

int CHolidaySet::FinalLeftSeconds(const QDate rDate, const QTime & rFinalTime,
                                  const  QMap<QDate, QVector<CWorkTime> >& rDateToWorkTime)
{
    if (rDateToWorkTime.find(rDate) == rDateToWorkTime.end()) return 0;
    const QVector<CWorkTime> & rVecWorkTime = rDateToWorkTime[rDate];
    if (rVecWorkTime.isEmpty()) return 0;
    return OneDayLeftSeconds(rVecWorkTime, rVecWorkTime.constFirst().mWorkStartTime, rFinalTime);
}

int CHolidaySet::OneDayLeftSeconds(const QVector<CWorkTime>& rVecWorkTime, const QTime & rStartTime, const QTime& rEndTime)
{
    if (rEndTime <= rStartTime) return 0;
    QVector<TFullTime> vecFullTime;
    for (unsigned int i = 0; i < rVecWorkTime.size(); ++i) {
        QTime timeStart;
        QTime timeEnd;
        if (0 == i) {
            timeStart.setHMS(0, 0, 0);
        }
        else {
            timeStart = rVecWorkTime[i - 1].mWorkEndTime;
        }

        TFullTime segTime1, segTime2;
        segTime1.mWorkTime.update(timeStart, rVecWorkTime[i].mWorkStartTime);
        segTime1.mbFlag = false;
        segTime2.mWorkTime = rVecWorkTime[i];
        segTime2.mbFlag = true;
        vecFullTime.push_back(segTime1);
        vecFullTime.push_back(segTime2);
        if (rVecWorkTime.size() - 1 == i) {
            timeEnd.setHMS(23, 59,59);
            TFullTime segTime3;
            segTime3.mWorkTime.update(rVecWorkTime[i].mWorkEndTime, timeEnd);
            segTime3.mbFlag = false;
            vecFullTime.push_back(segTime3);
        }
    }
    //qDebug() << CCommon::ToString(rStartTime) << " " << CCommon::ToString(rEndTime);

    for (unsigned int i = 0; i < vecFullTime.size(); ++i) {
        //qDebug() << CCommon::ToString(vecFullTime[i].mWorkTime.mWorkStartTime) << " " << CCommon::ToString(vecFullTime[i].mWorkTime.mWorkEndTime);
        if (rStartTime >= vecFullTime[i].mWorkTime.mWorkStartTime && rStartTime <= vecFullTime[i].mWorkTime.mWorkEndTime) {//找到起点所在区间
            int iValidStartIndex = -1;
            QTime realStartTime = rStartTime;
            if (!vecFullTime[i].mbFlag) {//起点在休息区间
                if (i == vecFullTime.size() - 1) {//最后一个休息区，则没有工作时间
                    return 0;
                }
                else {
                    if (rEndTime >= vecFullTime[i].mWorkTime.mWorkStartTime && rEndTime <= vecFullTime[i].mWorkTime.mWorkEndTime) {//开始与结束都在休息区
                        return 0;
                    }
                    else {//说明至少有工作时间
                        iValidStartIndex = i + 1;//真正工作区间
                        realStartTime = vecFullTime[iValidStartIndex].mWorkTime.mWorkStartTime;//更新实际开始时间
                    }
                }
            }
            else {
                iValidStartIndex = i;//实际开始时间就是rStartTime
            }
            int iValidEndIndex = -1;
            QTime realEndTime = rEndTime;
            for (unsigned int j = iValidStartIndex; j < vecFullTime.size(); ++j) {
                if (rEndTime >= vecFullTime[j].mWorkTime.mWorkStartTime && rEndTime <= vecFullTime[j].mWorkTime.mWorkEndTime) {
                    if (vecFullTime[j].mbFlag) {//在工作区间
                        iValidEndIndex = j;
                    }
                    else {//在休息区间
                        iValidEndIndex = j - 1;
                        realEndTime = vecFullTime[iValidEndIndex].mWorkTime.mWorkEndTime;
                    }
                    break;
                }
            }
            int iFreeTime = 0;
            for (unsigned int k = iValidStartIndex; k <= iValidEndIndex; ++k) {
                if (!vecFullTime[k].mbFlag) {
                    iFreeTime += vecFullTime[k].mWorkTime.mWorkStartTime.secsTo(vecFullTime[k].mWorkTime.mWorkEndTime);
                }
            }
            int iWorkTime = realStartTime.secsTo(realEndTime);
            iWorkTime -= iFreeTime;
            return iWorkTime;
        }
    }

    return 0;
}
